from decimal import Decimal
import json
import threading
from django.core.exceptions import ValidationError
from django.db import transaction, connection
from pymysql.converters import escape_string

from app.decorator import jwt_auth
from app.model.cs_goods_barcodes import CsGoodsBarcodes
from app.model.table_content_imgs import TableContentImgs
from app.model.table_goods import TableGoods
from app.model.table_shop_address import TableShopAddress
from app.model.table_thumbnail_imgs import TableThumbnailImgs
from app.service import goods_barcode, goods as goods_serv, goods_class,payment
from app.service.goods_barcode import get_shop_goods_id_by_barcode
from libs import common, time_helper,payment_lib
from libs.common import success, error, get_ts
from libs.db import DB
from libs.form import RawJsonForm

@jwt_auth
def goods_list(request, auth):
    form = RawJsonForm(request.body)
    p = form.get_page()
    total = 0
    goods_arr = []
    try:
        class_id = form.get_int('class_id')
        shop_id = auth.get('shop_id')
        filters = {
            'shoper_id': shop_id,
            'is_delete': 0
        }
        goods_name = form.get('goods_name')
        if goods_name != '':
            goods_name_filter = 'goods_name like "%{}%"'.format(escape_string(goods_name))
            filters.update({goods_name_filter: None})
        with connection.cursor() as cursor:
            if class_id > 0:
                class_ids_str = goods_class.get_children_by_pid(class_id, cursor)
                if class_ids_str == '':
                    filters.update({'class_id': class_id})
                else:
                    class_ids_str = '{},{}'.format(class_id, class_ids_str)
                    filters.update({'class_id in ({})'.format(class_ids_str): None})
            dh = DB('table_goods', conn=cursor)
            total = dh.count(filters)
            fields = goods_serv.GoodsListFields
            if total > 0:
                goods_arr = dh.order_by('sell_count desc').page(p).find(fields, filters)
                goods_id_arr = []
                for goods_item in goods_arr:
                    goods_id_arr.append(str(goods_item.get('id')))
                    goods_item.update({'point_ratio': goods_item.get('point_ratio') * 100})
                goods_img_map = goods_serv.query_goods_img_by_ids(goods_id_arr, cursor)
                goods_content_img_map = goods_serv.query_goods_content_in_ids(goods_id_arr, cursor)
                for goods_item in goods_arr:
                    goods_id = goods_item.get('id')
                    oss_url = goods_img_map.get(goods_id, '')
                    goods_item['goods_img'] = oss_url
                    oss_url = goods_content_img_map.get(goods_id, '')
                    goods_item['goods_content_img'] = oss_url
    except Exception as e:
        print(e.args)
    return success(goods_arr, total=total, page=p.page, size=p.size)


@jwt_auth
def goods_detail(request, auth):
    row = {}
    try:
        form = RawJsonForm(request.body)
        goods_id = form.get_int('id')
        if goods_id == 0:
            return error('无效的商品ID')
        shop_id = auth.get('shop_id')
        row = goods_serv.query_goods_by_id(shop_id, goods_id)
        if row.get('id', 0) > 0:
            row['point_ratio'] = common.to_dec(row['point_ratio']) * Decimal('100')
            row['goods_img'] = goods_serv.get_goods_img_by_id(goods_id)
            row['goods_content_img'] = goods_serv.get_goods_content_img_by_id(goods_id)
            class_id = row.get('class_id', 0)
            class_name = ''
            if class_id > 0:
                class_name = goods_class.query_goods_class_name(class_id)
            row['class_name'] = class_name
    except Exception as e:
        print(e)
    return success(row)


@jwt_auth
def add_goods(request, auth):
    form = RawJsonForm(request.body)
    shop_id = auth.get('shop_id')
    barcode = form.get('barcode')
    is_fast_food = form.get_int('is_fast_food')
    is_half = form.get_int('is_half')
    py_code = form.get('py_code')
    scale_no = form.get_int('scale_no', None)
    goods_image = form.get('img')
    content_image = form.get('content_img')
    unit = form.get('unit', '')
    json_result = json.loads(request.body)
    if 'drink_spec' in json_result:
        _drink_spec = json_result["drink_spec"]
        if len(_drink_spec) > 0:
            drink_spec = json.dumps(_drink_spec)
        else:
            drink_spec = ""
    else:
        drink_spec = ""
    if 'menu_desc' in json_result:
        _menu_desc = json_result["menu_desc"]
        if len(_menu_desc) > 0:
            menu_desc = json.dumps(_menu_desc)
        else:
            menu_desc = ""
    else:
        menu_desc = ""
    if 'drink_flavorset' in json_result:
        _drink_flavorset = json_result["drink_flavorset"]
        if len(_drink_flavorset) > 0:
            drink_flavorset = json.dumps(_drink_flavorset)
        else:
            drink_flavorset = ""
    else:
        drink_flavorset = ""
    if barcode.isnumeric() is False:
        return error('无效的条形码')
    db_goods_id = get_shop_goods_id_by_barcode(shop_id, barcode)
    if db_goods_id > 0:
        return error('商品已存在')
    class_id = form.get_int('class_id')
    if class_id == 0:
        return error('请选择分类')
    goods_name = form.get('goods_name')
    if goods_name == '':
        return error('商品名称不能为空')
    price = form.get('usdt_price')
    if price == '':
        return error('无效的商品价格')
    float_price = float(price)
    if float_price < 0:
        return error('无效的商品价格')
    member_price = form.get('member_price')
    if member_price == '':
        float_member_price = float_price
    else:
        float_member_price = float(member_price)
        if float_member_price < 0:
            return error('无效的会员价格')
    cost_price = form.get('cost_price')
    if cost_price == '':
        float_cost_price = float_price
    else:
        float_cost_price = float(cost_price)
        if float_cost_price < 0:
            return error('无效的商品进价')
    num = form.get('scount')
    num_dec = common.str_to_dec(num)
    if num_dec < 0:
        return error('无效的商品数量')
    product_date = form.get('product_date', None)
    guarantee_type = form.get_int('guarantee_type', None)
    guarantee_period = form.get_int('guarantee_period', None)

    try:
        point_ratio = form.get('point_ratio', None)
        if point_ratio is None:
            point_ratio_dec = Decimal('0.15')
        else:
            point_ratio_dec = (common.str_to_dec(point_ratio) * Decimal('0.01')).quantize(Decimal('0.00'))
        if point_ratio_dec > 1:
            point_ratio_dec = Decimal('1')
        guardian_ratio = form.get('guardian_ratio', '0')
        guardian_ratio_dec = common.str_to_dec(guardian_ratio) * Decimal('0.01')
        guardian_ratio = str(guardian_ratio_dec)
        if guardian_ratio_dec == Decimal('0'):
            guardian_ratio = float(point_ratio_dec + Decimal('0.01'))
        else:
            guardian_ratio = float(Decimal(guardian_ratio).quantize(Decimal('0.00')))
        if point_ratio_dec > 1:
            point_ratio_dec = Decimal('1')
        point_ratio = float(str(point_ratio_dec))
    except Exception as e:
        print('Decimal转换异常', e)
        point_ratio = 0
        guardian_ratio = 0.01

    try:
        now = get_ts()
        goods_data = TableGoods()
        goods_data.class_id = class_id
        goods_data.goods_name = goods_name
        goods_data.usdt_price = float_price
        goods_data.cost_price = float_cost_price
        goods_data.float_member_price = float_member_price
        goods_data.shoper_id = shop_id
        goods_data.state = 1
        goods_data.is_hot = 0
        goods_data.is_ban = 0
        goods_data.create_time = time_helper.ts_to_time_str(time_format="%Y-%m-%d %H:%M:%S")
        goods_data.from_type = 1
        goods_data.is_community = 1
        goods_data.is_warehouse = 0
        goods_data.device_goods_id = '{}_{}'.format(shop_id, barcode)
        goods_data.py_code = py_code
        goods_data.updated = now
        goods_data.point_ratio = point_ratio
        goods_data.guardian_ratio = guardian_ratio
        goods_data.is_fast_food = is_fast_food
        goods_data.is_half = is_half
        if product_date is not None:
            product_ts = time_helper.time_str_to_ts(product_date)
            if product_ts > 0:
                goods_data.product_date = product_date
        if guarantee_period is not None:
            goods_data.guarantee_period = guarantee_period
        if guarantee_type is not None:
            goods_data.guarantee_type = guarantee_type

        if scale_no is not None:
            if scale_no >= 0:
                goods_data.scale_no = scale_no
                if len(barcode) != 5:
                    return error('称重商品条形码为5位')
                goods_data.spec_typ = 1
                unit = '千克'
        goods_data.barcode = barcode
        goods_data.scount = num_dec
        goods_data.unit = unit
        goods_data.drink_spec = drink_spec
        goods_data.menu_desc = menu_desc
        goods_data.drink_flavorset = drink_flavorset
        with transaction.atomic():
            goods_data.save()
            cs_goods_barcodes = CsGoodsBarcodes()
            cs_goods_barcodes.goods_id = goods_data.id
            cs_goods_barcodes.shop_id = shop_id
            cs_goods_barcodes.barcode = barcode
            cs_goods_barcodes.save()
            if goods_image != "":
                table_thumbnail_imgs = TableThumbnailImgs()
                table_thumbnail_imgs.goods_id = goods_data.id
                table_thumbnail_imgs.oss_url = goods_image
                table_thumbnail_imgs.is_delete = 0
                table_thumbnail_imgs.order_id = 0
                table_thumbnail_imgs.save()
            if content_image != "":
                table_content_imgs = TableContentImgs()
                table_content_imgs.goods_id = goods_data.id
                table_content_imgs.oss_url = goods_image
                table_content_imgs.is_delete = 0
                table_content_imgs.order_id = 0
                table_content_imgs.save()
    except ValidationError as e:
        err = '数据验证失败'
        print(err, e)
        err += '({})'.format(str(e))
        return error(err)
    except Exception as ex:
        print(ex)
        msg = ''
        if len(ex.args) > 0 and ex.args[0] == 1062:
            msg = '商品已存在'
        return error(msg)
    goods_barcode.save_barcode_archives({
        'barcode': barcode,
        'goods_name': goods_name,
        'price': float_price,
        'cost_price': float_cost_price,
        'unit': unit,
        'created': now
    })
    return success()


@jwt_auth
def add_barcode(request, auth):
    form = RawJsonForm(request.body)
    shop_id = auth.get('shop_id')
    barcode = form.get('barcode')
    if barcode.isnumeric() is False:
        return error('无效的条形码')
    db_goods_id = get_shop_goods_id_by_barcode(shop_id, barcode)
    if db_goods_id > 0:
        return error('条形码已存在')
    goods_id = form.get('goods_id')
    if goods_id == 0:
        return error('无效的商品ID')
    db_goods_data = goods_serv.query_goods_by_id(shop_id, goods_id)
    db_goods_id = db_goods_data.get('id', 0)
    if db_goods_id == 0:
        return error('商品不存在')
    try:
        cs_goods_barcodes = CsGoodsBarcodes()
        cs_goods_barcodes.goods_id = db_goods_id
        cs_goods_barcodes.shop_id = shop_id
        cs_goods_barcodes.barcode = barcode
        cs_goods_barcodes.full_clean()
        cs_goods_barcodes.save()
    except ValidationError as e:
        msg_arr = []
        for (k, item) in e.message_dict.items():
            msg_arr.append('{}:{}'.format(k, ';'.join(item)))
        return error(';'.join(msg_arr))
    except Exception as ex:
        msg = ''
        if str(ex).index('(1062,') == 0:
            msg = '店铺条形码已存在'
        return error(msg)
    return success()


@jwt_auth
def update_goods(request, auth):
    form = RawJsonForm(request.body)
    try:
        goods_id = form.get_int('id')
        if goods_id == 0:
            return error('无效的商品ID')
        update_data = {}
        goods_name = form.get('goods_name')
        if goods_name != '':
            update_data['goods_name'] = goods_name
        class_id = form.get_int('class_id')
        if class_id > 0:
            update_data['class_id'] = class_id
        price = form.get('usdt_price')
        if price != '':
            float_price = float(price)
            if float_price < 0:
                return error('无效的商品价格')
            update_data['usdt_price'] = float_price
        cost_price = form.get('cost_price')
        if cost_price != '':
            float_cost_price = float(cost_price)
            if float_cost_price < 0:
                return error('无效的商品进价')
            update_data['cost_price'] = float_cost_price
        member_price = form.get('member_price')
        if member_price != '':
            float_member_price = float(member_price)
            if float_member_price < 0:
                return error('无效的会员价格')
            update_data['member_price'] = float_member_price
        product_date = form.get('product_date', None)
        if product_date is not None:
            update_data['product_date'] = product_date
        guarantee_type = form.get_int('guarantee_type', None)
        if guarantee_type is not None:
            update_data['guarantee_type'] = guarantee_type
        guarantee_period = form.get_int('guarantee_period', None)
        if guarantee_period is not None:
            update_data['guarantee_period'] = guarantee_period
        goods_image = form.get('img', None)
        content_image = form.get('content_img', None)
        with connection.cursor() as cursor:
            if goods_image is not None:
                goods_serv.save_goods_image(cursor, goods_id, goods_image)
            if content_image is not None:
                goods_serv.save_goods_content_image(cursor, goods_id, content_image)
        py_code = form.get('py_code')
        if py_code != '':
            update_data['py_code'] = py_code
        unit = form.get('unit', None)
        if unit is not None:
            update_data['unit'] = unit
        barcode = form.get_int('barcode', None)
        if barcode is not None:
            update_data['barcode'] = barcode
        shop_id = auth.get('shop_id')
        goods_history_data = goods_serv.query_goods_by_id(shop_id, goods_id, None)
        try:
            point_ratio = form.get_dec('point_ratio', None)
            if point_ratio is not None:
                point_ratio = float((Decimal(point_ratio) * Decimal('0.01')).quantize(Decimal('0.00')))
                if point_ratio > 1:
                    point_ratio = 1
                update_data['point_ratio'] = point_ratio
            guardian_ratio = form.get_dec('guardian_ratio', None)
            if guardian_ratio is not None:
                guardian_ratio = float((Decimal(guardian_ratio) * Decimal('0.01')).quantize(Decimal('0.00')))
                if guardian_ratio > 1:
                    guardian_ratio = 1
                update_data['guardian_ratio'] = guardian_ratio
        except Exception as e:
            print('Decimal转换异常', e)
        filters = {
            'id': goods_id,
            'shoper_id': shop_id
        }
        TableGoods.objects.filter(**filters).update(**update_data)
        # 保存商品历史数据
        if goods_history_data.get('id') == goods_id:
            goods_serv.save_goods_history_data(goods_id, goods_history_data)
    except Exception as e:
        print(e.args)
        return error('更新商品信息失败')
    return success()


@jwt_auth
def del_goods(request, auth):
    form = RawJsonForm(request.body)
    goods_id = form.get_int('id')
    if goods_id == 0:
        return error('无效的商品ID')
    try:
        shop_id = auth.get('shop_id')
        filters = {
            'id': goods_id,
            'shoper_id': shop_id
        }
        goods_obj = TableGoods.objects.filter(**filters).get()
        if goods_obj.id == 0:
            return error('商品不存在')
        if goods_obj.state != 0:
            return error('商品已提交，无法删除')
        update_data = {
            'is_delete': 1
        }
        TableGoods.objects.filter(**filters).update(**update_data)
    except Exception as e:
        print(e.args)
    return success()


@jwt_auth
def query_goods(request, auth):
    form = RawJsonForm(request.body)
    page = form.get_page()
    total, goods_arr, weight_str, shop_is_half, resp_ext = goods_serv.query_goods_by_keyword(form, auth, page)
    return success(goods_arr,
                   total=total,
                   page=page.page,
                   size=page.size,
                   weight=weight_str,
                   shop_is_half=shop_is_half,
                   **resp_ext)


@jwt_auth
def query_goods_v2(request, auth):
    form = RawJsonForm(request.body)
    page = form.get_page()
    total, goods_arr, weight_str, shop_is_half, _ = goods_serv.query_goods_by_keyword(form, auth, page, True)
    return success(goods_arr,
                   total=total,
                   page=page.page,
                   size=page.size,
                   weight=weight_str,
                   shop_is_half=shop_is_half)
                   
@jwt_auth
def drinksetting(request, auth):
    try:
        result = []
        cursor = connection.cursor()
        shop_id = auth.get('shop_id')
        _sql = 'select id did,name from table_drink_setting where shop_id=%s and status=0 and pid=0'
        bindings = [shop_id]
        cursor.execute(_sql,bindings)
        rows = cursor.fetchall()
        if rows is not None:
            for row in rows:
                _item = {}
                child = []
                did,name = row
                _sql1 = 'select id did,name from table_drink_setting where shop_id=%s and status=0 and pid=%s'
                bindings1 = [shop_id,did]
                cursor.execute(_sql1,bindings1)
                rows1 = cursor.fetchall()
                if rows1 is not None:
                    for row1 in rows1:
                        _item1 = {}
                        did1,name1 = row1
                        _item1.update({
                            'id': did1,
                            'name':name1
                        })
                        child.append(_item1)
                _item.update({
                    'name': name,
                    'child':child
                })
                result.append(_item)
        return success(result)
    except Exception as e:
        print(e.args)
    return success()

@jwt_auth
def ticketsetting(request, auth):
    form = RawJsonForm(request.body)
    ticket_count = form.get_int('ticket_count',1)
    shop_id = auth.get('shop_id')
    try:
        filters = {
            'id': shop_id
        }
        update_data = {
            'ticket_count': ticket_count
        }
        TableShopAddress.objects.filter(**filters).update(**update_data)
    except Exception as e:
        print(e.args)
    return success()

@jwt_auth
def getticketsetting(request, auth):
    form = RawJsonForm(request.body)
    shop_id = auth.get('shop_id')
    try:
        filters = {
            'id': shop_id
        }
        shop_obj = TableShopAddress.objects.filter(**filters).values(*['ticket_count']).get()
        return success(shop_obj)
    except Exception as e:
        print(e.args)

@jwt_auth
def getfastfood(request, auth):
    try:
        cursor = connection.cursor()
        shop_id = auth.get('shop_id')
        filters = {
            'shoper_id': shop_id,
            'is_delete': 0
        }
        filters.update({'is_fast_food in (1,2)': None})
        result = DB('table_goods',conn=cursor).find(['id','goods_name','usdt_price','is_fast_food','drink_spec','drink_flavorset'],filters)
        return success(result)
    except Exception as e:
        print(e.args)

@jwt_auth
def getshopinfo(request, auth):
    try:
        result = {
            'is_fastshop':0,
            'charge_list':[]
        }
        cursor = connection.cursor()
        shop_id = auth.get('shop_id')
        shop_info = DB('table_shop_address',conn=cursor).one(['is_fastshop'],{'id':shop_id})
        result.update({'is_fastshop': shop_info.get('is_fastshop',0)})
        filters = {
            'shop_id': shop_id,
            'status': 0
        }
        result_type = DB('table_fastballance_type',conn=cursor).find(['id','chargemoney','givemoney','realmoney'],filters)
        result.update({'charge_list':result_type})
        return success(result)
    except Exception as e:
        print(e.args)

@jwt_auth
def chargefastballance_back(request, auth):
    try:
        cursor = connection.cursor()
        shop_id = auth.get('shop_id')
        form = RawJsonForm(request.body)
        type_id = form.get_int('type_id',0)
        username = form.get('username',"")
        if type_id == 0:
            return error('充值金额不存在')
        if username == "":
            return error('充值会员不能为空')
        c_info = DB('table_fastballance_type',conn=cursor).one(['realmoney'],{'id':type_id})
        realmoney = c_info.get('realmoney',0)
        if realmoney == 0:
            return error('充值金额异常')
        u_info = DB('table_member',conn=cursor).one(['id','username','fast_ballance'],{'username':username})
        u_id = u_info.get('id',0)
        if u_id == 0:
            return error('充值用户不存在')
        before_ballance = u_info.get('fast_ballance',0)
        after_ballance = before_ballance + realmoney
        DB('table_member',conn=cursor).update({'fast_ballance': after_ballance,'is_fastmember':1},{'id':u_id})
        insert_flow = {
            'username':username,
            'before_value':before_ballance,
            'after_value':after_ballance,
            'amount':realmoney,
            'type':1,
            'charge_type':type_id
        }
        DB('table_fastballance_flow',conn=cursor).insert(insert_flow)
        return success()
    except Exception as e:
        print(e.args)

@jwt_auth
def chargefastballance(request, auth):
    try:
        cursor = connection.cursor()
        shop_id = auth.get('shop_id')
        form = RawJsonForm(request.body)
        type_id = form.get_int('type_id',0)
        username = form.get('username',"")
        if type_id == 0:
            return error('充值金额不存在')
        if username == "":
            return error('充值会员不能为空')
        pay_mode = form.get_int('pay_mode') # 1 现金 10 线下扫码 100 微信/支付宝
        if pay_mode == 0:
            return error('无效的支付类型')
        pay_code = form.get_int('pay_code') # 付款码
        c_info = DB('table_fastballance_type',conn=cursor).one(['realmoney','chargemoney'],{'id':type_id})
        realmoney = c_info.get('realmoney',0)
        chargemoney = c_info.get('chargemoney',0)
        if realmoney == 0 or chargemoney == 0:
            return error('充值金额异常')
        u_info = DB('table_member',conn=cursor).one(['id','username','fast_ballance'],{'username':username})
        u_id = u_info.get('id',0)
        if u_id == 0:
            return error('充值用户不存在')
        if pay_mode == 100:  # 微信或支付宝
            pay_code_info = payment_lib.get_pay_code_type(pay_code)
            if type(pay_code_info) is dict:
                third_party_pay_flag = pay_code_info.get('code')
            else:
                return error('无效的第三方支付方式')
            if third_party_pay_flag == 1:
                pay_mode = 2
            elif third_party_pay_flag == 2:
                pay_mode = 3
            ip = common.get_ip(request)
            # 创建第三方充值支付订单
            cashier_id = str(auth.get('cashier_id'))
            order_sn = payment.gen_pay_order_sn(3)
            rowid, err = payment.create_top_up_order(cursor, {
                'cashier_id': cashier_id,
                'order_sn': order_sn,
                'pay_yuan': chargemoney,
                'order_args': json.dumps({
                    'card_id': type_id,
                    'username': username,
                    'pay_mode': pay_mode,
                    'num': 1,
                }),
                'ip': ip,
                'order_typ': 3,
            })
            if not (err is None and rowid > 0):
                return error('充值订单创建失败')
            th = threading.Thread(target=payment.process_top_up_payment_fast, args=(cashier_id,
                                                                                   order_sn,
                                                                                   third_party_pay_flag,
                                                                                   pay_code,
                                                                                   username,
                                                                                   pay_mode,
                                                                                   realmoney,
                                                                                   chargemoney,
                                                                                   type_id,
                                                                                   ))
            th.start()
            return success(order_sn=order_sn)
        else:
            app_pay_mode_dict = {
                1: 4,
                10: 7,
            }
            if pay_mode not in app_pay_mode_dict:
                return error('无效的支付方式') 
            app_pay_mode = app_pay_mode_dict.get(pay_mode)
            before_ballance = u_info.get('fast_ballance',0)
            after_ballance = before_ballance + realmoney
            DB('table_member',conn=cursor).update({'fast_ballance': after_ballance,'is_fastmember':1},{'id':u_id})
            insert_flow = {
                'username':username,
                'before_value':before_ballance,
                'after_value':after_ballance,
                'amount':realmoney,
                'type':1,
                'charge_type':type_id,
                'charge_mode':app_pay_mode,
                'charge_money':chargemoney
            }
            DB('table_fastballance_flow',conn=cursor).insert(insert_flow)
            return success()
    except Exception as e:
        print(e)
        err = '充值异常'
        return error(err)